<html>
<head>
  <script src="../../lib/OpenLayers.js"></script>
  <script src="../../lib/OpenLayers/Layer/ArcGISCache.js" type="text/javascript"></script>
  <script src="ArcGISCache.json" type="text/javascript"></script>
  <script type="text/javascript">
    var isMozilla = (navigator.userAgent.indexOf("compatible") == -1);
    var layer; 

    var name = 'Test Layer';
    var url = "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer";
    var options = { }; 

    function test_Layer_ARCGISCACHE_constructor (t) {
        t.plan( 1 );
                       
        var layer = new OpenLayers.Layer.ArcGISCache(name, url, options);
        t.ok( layer instanceof OpenLayers.Layer.ArcGISCache, "returns OpenLayers.Layer.ArcGISCache object" );
    }
    
    function test_Layer_ARCGISCACHE_autoConfigure (t) {
        t.plan( 5 );
        var layerInfo = capabilitiesObject;
        
        //initialize the layer using the JSON object from an arcgis server
        //SEE: ArcGISCache.json
        var layer = new OpenLayers.Layer.ArcGISCache(name, url, {
            layerInfo: layerInfo
        });
        t.ok( layer instanceof OpenLayers.Layer.ArcGISCache, "returns OpenLayers.Layer.ArcGISCache object" );        
        t.ok( layer.projection = 'EPSG:' + layerInfo.spatialReference.wkid, "projection is set correctly");
        t.ok( layer.units = 'm', "map units are set correctly");
        t.ok( layer.resolutions && layer.resolutions.length == 20, "resolutions are initialized from LOD objects properly");
        
        if (layerInfo.tileInfo) {
            if (layerInfo.tileInfo.width && layerInfo.tileInfo.height) {
                var tileSize = new OpenLayers.Size(layerInfo.tileInfo.width, layerInfo.tileInfo.height);
                t.ok((layer.tileSize.width == tileSize.width) && (layer.tileSize.height == tileSize.height), "tile size is set properly");
            }
            else {
                var tileSize = new OpenLayers.Size(layerInfo.tileInfo.cols, layerInfo.tileInfo.rows);
                t.ok((layer.tileSize.width == tileSize.width) && (layer.tileSize.height == tileSize.height), "tile size is set properly");
            }
        }        
    }
    
    /**
     * lets make sure we're getting the correct urls back with a basic auto-configure setup 
     */
    function test_Layer_ARCGISCACHE_autoConfigure_URLS(t) {
        var layerInfo = capabilitiesObject;
        
        //initialize the layer using the JSON object from an arcgis server
        //SEE: ArcGISCache.json
        var layer = new OpenLayers.Layer.ArcGISCache(name, url, {
            layerInfo: layerInfo,
            params: {foo: "bar"}
        });
        var map = new OpenLayers.Map('map', { 
            maxExtent: layer.maxExtent,
            units: layer.units,
            resolutions: layer.resolutions,
            numZoomLevels: layer.numZoomLevels,
            tileSize: layer.tileSize,
            projection: layer.displayProjection,
            StartBounds: layer.initialExtent    
        });
        map.addLayers([layer]);
    
        //this set represents a few edge cases, and some more specific cases, it is by no means exhaustive,
        var urlSets = [
            { 
                bounds: new OpenLayers.Bounds(-36787612.973083,-22463925.368666, 43362420.398053,17611091.316902),
                url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/0/0/0" 
            },            
            { 
                bounds: new OpenLayers.Bounds(-31793889.951914,4589319.785415, 8281126.733654,24626828.128199),
                url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/1/0/0"
            },            
            { 
                bounds: new OpenLayers.Bounds(-24639873.181971,12676071.933457, -4602364.839187,22694826.104849),
                url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/2/0/0" 
            },
            { 
                bounds: new OpenLayers.Bounds(-15521241.455665,11580270.695961, 4516266.887119,21599024.867353),
                url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/2/0/1" 
            },                    
            { 
                bounds: new OpenLayers.Bounds(-9265879.5435993,2870892.9335638, -8639707.4078873,3183979.0014198) ,
                url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/7/54/35" 
            },
            { 
                bounds: new OpenLayers.Bounds(-10741909.131798,4684560.1640365, -10585366.09787,4762831.6810005),
                url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/9/195/119" 
            },
            { 
                bounds: new OpenLayers.Bounds(-13668958.106938,4456961.2611504, -13512415.07301,4535232.7781144),
                url: "http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/9/198/82" 
            }
        ];
        
        t.plan( urlSets.length );
        for(var i=0;i<urlSets.length;i++) 
        {
            var o = urlSets[i];            
            map.zoomToExtent(o.bounds, true);
            
            var resultUrl = layer.getURL(o.bounds);            
            t.ok( resultUrl == o.url + "?foo=bar", "correct tile returned for " + o.bounds);        
        }
    }    
    
    /**
     * Test the formatting for the 'direct' urls, especially when not auto-configuring the layer
     */
    function test_Layer_ARCGISCACHE_direct(t) {
        var roadsUrl = 'http://serverx.esri.com/arcgiscache/DG_County_roads_yesA_backgroundDark/Layers/_alllayers';
        var urlSets = [
            { 
                bounds: new OpenLayers.Bounds(289244.67443386,4317153.7421985, 306178.04163392,4325620.4257985),
                url: roadsUrl + "/L00/R0000029e/C0000027f.png" 
            },            
            { 
                bounds: new OpenLayers.Bounds(308658.51534463,4303230.0164352, 325591.88254469,4311696.7000352),
                url: roadsUrl + "/L00/R000002a0/C00000282.png"
            },            
            { 
                bounds: new OpenLayers.Bounds(311136.39626998,4318933.8711555, 311678.26402038,4319204.8050307) ,
                url: roadsUrl + "/L05/R000051e0/C00004e52.png" 
            }
        ];
        t.plan( urlSets.length );
    
    
        //perform the exact setup from the arcgiscache_direct example
            
        // First 4 variables extracted from conf.xml file        
        // Tile layers & map MUST have same projection 
        var proj='EPSG:26915';
            
        // Layer can also accept serverResolutions array
        // to deal with situation in which layer resolution array & map resolution
        // array are out of sync
        var mapResolutions = [33.0729828126323,16.9333672000677,8.46668360003387,4.23334180001693,2.11667090000847,1.05833545000423];

        // For this example this next line is not really needed, 256x256 is default.
        // However, you would need to change this if your layer had different tile sizes 
        var tileSize = new OpenLayers.Size(256,256);
        
        // Tile Origin is required unless it is the same as the implicit map origin
        // which can be effected by several variables including maxExtent for map or base layer 
        var agsTileOrigin = new OpenLayers.LonLat(-5120900,9998100);
        
        // This can really be any valid bounds that the map would reasonably be within 
        var mapExtent = new OpenLayers.Bounds(289310.8204,4300021.937,314710.8712,4325421.988);
        

        var map = new OpenLayers.Map('map', {
            maxExtent:mapExtent,
            controls: [
                new OpenLayers.Control.Navigation(),
                new OpenLayers.Control.LayerSwitcher(), 
                new OpenLayers.Control.PanZoomBar(),
                new OpenLayers.Control.MousePosition()]
        });

        var layer = new OpenLayers.Layer.ArcGISCache('Roads', roadsUrl, {
            tileOrigin: agsTileOrigin,
            resolutions: mapResolutions,
            sphericalMercator: true,
            maxExtent: mapExtent,
            useArcGISServer: false,
            isBaseLayer: true,
            projection: proj
        });
        
        map.addLayers([layer]);
        map.zoomToExtent(new OpenLayers.Bounds(-8341644, 4711236, -8339198, 4712459));

        for(var i=0;i<urlSets.length;i++) 
        {
            var o = urlSets[i];            
            map.zoomToExtent(o.bounds, true);
            var resultUrl = layer.getURL(o.bounds);
            t.ok( resultUrl == o.url, "correct tile returned for " + o.bounds);        
        }
    }
        
    /**
     * Check the utility function for generating tile indexes against a file cache
     * This is already tested in BaseTypes test, but these are specific,
     * common conversions that this class will rely on, so the tests are retained
     */
    function test_Layer_ARCGISCACHE_zeroPad(t) {
        t.plan(4);
    
        var layer = new OpenLayers.Layer.ArcGISCache('test', null, { });

        //some tile examples
        t.ok('00000001' == OpenLayers.Number.zeroPad(1, 8, 16), 'zeroPad should generate tile indexes properly ');
        t.ok('00000020' == OpenLayers.Number.zeroPad(32, 8, 16), 'zeroPad should generate tile indexes properly ');
        t.ok('00000100' == OpenLayers.Number.zeroPad(256, 8, 16), 'zeroPad should generate tile indexes properly ');
        t.ok('00001000' == OpenLayers.Number.zeroPad(4096, 8, 16), 'zeroPad should generate tile indexes properly ');        
    }
    
    /**
     * Check to ensure our LOD calculation will correctly avoid returning tile indexes less than zero
     * (see http://trac.osgeo.org/openlayers/ticket/3169)
     */
    function test_Layer_ARCGISCACHE_tileBounds(t) {
        t.plan(1);
    
        var layer = new OpenLayers.Layer.ArcGISCache('test', null, { });
        var res = 264.583862501058;
        layer.tileOrigin = new OpenLayers.LonLat(0.0, 650000.0);
        layer.tileSize = new OpenLayers.Size(512, 512);
        
        // pick a point off the left of our tile origin  (would be a negative tile index)
        var point = new OpenLayers.Geometry.Point(-123308.94829, 393128.85817);
        
        var tile = layer.getContainingTileCoords(point, res);
        t.ok((tile.x >= 0 && tile.y >= 0), 'layer should not generate negative tile ranges for level of detail');
    }

   /*  
    * Test that messing up the Array.prototype does not mess up the lods of the layer. 
    * This messes up zooming when resolutions are very small/scales are very large/zoomed way in. 
    */ 
    function test_Layer_ARCGISCACHE_lods (t) { 
        t.plan( 2 ); 
        var layerInfo = capabilitiesObject; 

        lods = layerInfo.tileInfo.lods.length; 

        // mess up the Array prototype
        Array.prototype.foo = function() { };

        t.ok( lods == layerInfo.tileInfo.lods.length, 'proper number of "Levels of Detail" before initialization' ); 

        // initialize the layer using the JSON object from an arcgis server 
        // see: ArcGISCache.json 
        var layer = new OpenLayers.Layer.ArcGISCache(name, url, { 
            layerInfo: layerInfo 
        }); 

        t.ok( lods == layer.lods.length, 'proper number of "Levels of Detail" after initialization.' );         
        // restore the Array prototype
        delete Array.prototype.foo;
    } 

  </script>
</head>
<body>
<div id="map" style="width:500px;height:550px;"></div>
</body>
</html>
